package com.jiuli_travel.blog_service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiuli_travel.blog_service.mapper.TeamMapper;
import com.jiuli_travel.blog_service.model.dto.team.CategorySearchTeamRequest;
import com.jiuli_travel.blog_service.model.dto.team.JoinTeamRequest;
import com.jiuli_travel.blog_service.model.dto.team.TeamInsertRequest;
import com.jiuli_travel.blog_service.model.entity.Team;
import com.jiuli_travel.blog_service.model.entity.UserTeam;
import com.jiuli_travel.blog_service.model.enums.TeamStatusEnum;
import com.jiuli_travel.blog_service.model.vo.TeamVO;
import com.jiuli_travel.blog_service.service.ITeamService;
import com.jiuli_travel.blog_service.service.IUserTeamService;
import com.jiuli_travel.user_service.model.cache.UserCache;
import com.jiuli_travel.user_service.model.vo.UserVO;
import com.jiuli_travel.utils.MinDistanceUtil;
import com.jiuli_travel.utils.Result;
import com.jiuli_travel.utils.UserHolder;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jiuli
 * @since 2024-04-11
 */
@Service
@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements ITeamService {

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private IUserTeamService userTeamService;

    @Autowired
    private TeamMapper teamMapper;

    // 发起团队
    @Override
    public Result publishTeam(TeamInsertRequest teamInsertRequest) {
        //获取当前用户的id
        UserVO userVO = UserHolder.getUser();

        //valid
        // TODO 1. 参数校验 （不为空什么的)
//        if(teamInsertRequest.getTeamName() == null){
//            return Result.fail("密码不能为空");
//        }

        // 2. 是否有权限去发起团队
        if (Objects.equals(userVO.getTeamStatus(), TeamStatusEnum.DISABLE.getValue())){
            return Result.fail("你当前没有权限进行加入团队和组团");
        }

        // 查询该用户的所有团队出来
        List<Team> teamList = list();
        // 3. 发起人最多发起五个团队
        if(teamList.size() >= 5){
            return Result.fail("发起团队达到上限");
        }
        // 4. 个人发起的团队的名字不能重复
        long count = teamList.stream().filter(team -> team.getTeamName().equals(teamInsertRequest.getTeamName())).count();
        if(count > 0){
            return Result.fail("团队名称不能重复");
        }

        // 4. 符合要求，进行发起团队
        //格式转化
        Team team = BeanUtil.copyProperties(teamInsertRequest, Team.class);
        //设置发起人id
        team.setUserId(userVO.getId());
        //插入数据
        boolean save = save(team);

        // 5. 插入我自己到user-team中
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userVO.getId());
        userTeam.setTeamId(team.getId());
        userTeamService.save(userTeam);

        return Result.ok("创建队伍成功");
    }

    // 加入团队
    @Override
    public Result joinTeam(JoinTeamRequest joinTeamRequest) {
        //获取当前用户的信息
        UserVO userVO = UserHolder.getUser();

        // 判断该用户是否已经加入了该团队，幂等性
        Long count = userTeamService.lambdaQuery()
                .eq(UserTeam::getUserId, userVO.getId())
                .eq(UserTeam::getTeamId, joinTeamRequest.getTeamId())
                .count();
        if(count >= 1){
            //有人来攻击，记录一下日志
            log.info("com.jiuli_travel.blog_service.service.impl.TeamServiceImpl: 你加入过了");
            return Result.fail("你加入过了");
        }

        /**
         * 校验是否符合可以加入此团队
         */
        Team team = getById(joinTeamRequest.getTeamId());
        // validExist
        if(team == null){
            return Result.fail("该团队不存在");
        }
        // 1. 判断该团队是否已经禁用 （也就是是否过期了）
        if(Objects.equals(team.getStatus(), TeamStatusEnum.DISABLE.getValue())){
            return Result.fail("该团队已经快出发啦，不能加入了");
        }
        // TODO 2. 校验地理位置是否符合我所定义的位置
        // TODO 3. 当前用户是否有资格加入队伍（如果用户多次加入队伍后，但是有没有去旅行的话，短期内，是不能加入旅行团队的）
        // 4. status为私密（0）的话，需要密码验证
        if(team.getStatus() == 0){
            if(joinTeamRequest.getPassword() == null || !joinTeamRequest.getPassword().equals(team.getPassword())){
                return Result.fail("密码输入异常");
            }
        }
        // 5. 判断团队人数是否达到指定数量， 得用悲观锁（就是判断与修改同时进行）TODO 这里update里面的更新还不熟悉， 用xml
        if(teamMapper.updateTeamY(joinTeamRequest.getTeamId()) <= 0){
            return Result.fail("加入人数已达上限");
        }

        //进行插入user-team表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userVO.getId());
        userTeam.setTeamId(joinTeamRequest.getTeamId());
        userTeamService.save(userTeam);

        return Result.ok("加入成功");
    }

    // 分类标签搜索团队
    @Override
    public void categorySearchTeam(CategorySearchTeamRequest searchTeamRequest) {
        //构建查询条件
        // 是否有根据最近出行时间进行排序？
        Page<Team> mp = null;
        if(searchTeamRequest.isRecently()){
            searchTeamRequest.toMp(new OrderItem("departure_time", false));
        }else {
            mp = searchTeamRequest.toMp();
        }

        LambdaQueryChainWrapper<Team> queryWrapper = lambdaQuery();
        // 1. 根据标签去查
        if(searchTeamRequest.getTag() != null){
            queryWrapper.eq(Team::getTags, searchTeamRequest.getTag());
        }
        // 2. 根据地理位置去查
        if(searchTeamRequest.getPosition() != null){
            queryWrapper.eq(Team::getPosition, searchTeamRequest.getPosition());
        }
        // 3. 默认推荐
    }

    // 推荐团队信息
    private List<TeamVO> recommendTeam(){
        // 1. 根据平时搜索的内容的tag进行一个分析（搜索，点击记录？）
        // 2. 根据我所处的地理位置信息
        // 3. 根据搜索词推荐
        return null;
    }

    // TODO 搜索框搜索团队（现根据团队名称进行搜索）
    @Override
    public List<TeamVO> searchTeam(String searchText, Integer size) {

        // 1. valid
        if("".equals(searchText)){
            return null;
        }
        // 2. 模糊查询出所有团队主句
        List<Team> teamList = lambdaQuery()
                .like(Team::getTeamName, searchText)
                .eq(Team::getIsDeleted, 0)
                .ge(Team::getStatus, TeamStatusEnum.PUBLIC.getValue())
                .list();

        // 3. 查询策略， 编辑距离算法
        Map<Team, Integer> teamMap = new HashMap<>();
        teamList.stream().forEach(team -> {
            int score = MinDistanceUtil.minDistance(team.getTeamName(), searchText);
            teamMap.put(team, score);
        });

        // 4. 根据分数进行排序
        teamList = teamMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        // 列表尺寸大于所需，按所需， 否则全部返回
        List<Team> teams = teamList.subList(0, size <= teamList.size() ? size : teamList.size());

        // 5. 转化数据格式
        List<TeamVO> teamVOs = BeanUtil.copyToList(teams, TeamVO.class);

        // TODO 6. 封装各类信息

        return teamVOs;
    }

    // 解散团队
    @Override
    public void disbandTeam(Long teamId) {
        // 1. 获取当前登录的用户的信息
        Long loginUserId = UserHolder.getUser().getId();

        // 2. 查询该团队的队长是不是当前登录的用户
        Long count = lambdaQuery()
                .eq(Team::getId, teamId)
                .eq(Team::getUserId, loginUserId)
                .count();

        // 3. 删除该团队里面所有的user-team 信息
        LambdaQueryChainWrapper<UserTeam> delWrapper = userTeamService
                .lambdaQuery()
                .eq(UserTeam::getTeamId, teamId);
        userTeamService.remove(delWrapper);

    }

    // 踢出成员
    @Override
    public void kickOutOfTheTeam(Long teamId, Long userId) {
        // 1. 获取当前登录的用户的信息
        Long loginUserId = UserHolder.getUser().getId();

        // 2. 查询该团队的队长是不是当前登录的用户
        Long count = lambdaQuery()
                .eq(Team::getId, teamId)
                .eq(Team::getUserId, loginUserId)
                .count();
        if(count >=0 ){
            leaveTeamP(teamId, userId);
        }
    }

    // 退出队伍
    @Override
    public void leaveTeam(Long teamId) {
        // 1. 获取当前登录的用户的信息
        Long loginUserId = UserHolder.getUser().getId();

        // 2. 退出
        leaveTeamP(teamId, loginUserId);
    }


    // 单个人退出队伍（禁用了也可以退出队伍丫）
    public void leaveTeamP(Long teamId, Long userId) {
        // 1. 删除用户团队信息表 （该中间信息存在， 删除成功 不存在，或者已经删除， 删除失败）
        // 构建删除条件并删除
        boolean remove = userTeamService
                .lambdaUpdate()
                .eq(UserTeam::getTeamId, teamId)
                .eq(UserTeam::getUserId, userId)
                .remove();
        if(!remove){
            log.info("你不在该团队当中");
        }

        // 2. 将团队表中的当前人数进行更新
        boolean update = lambdaUpdate()
                .eq(Team::getId, teamId)
                .setSql("current_members = current_members - 1")
                .update();
    }
}



























